/**niushop */
import axios from 'axios'
import { config } from '@/config/axios/config'
const { base_url, request_timeout } = config
import type {
  AxiosInstance,
  InternalAxiosRequestConfig,
  AxiosResponse,
  AxiosRequestConfig
} from 'axios'
import { isUrl } from './common'
import { ElMessage } from 'element-plus'
import type { MessageParams } from 'element-plus'
const { t } = useI18n() // 国际化
// 是否显示重新登录
export const isRelogin = { show: false }
import { getAccessToken, getTenantId, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
import { deleteUserCache } from '@/hooks/web/useCache'
import { useLocaleStoreWithOut } from '@/store/modules/locale'
const localeStore = useLocaleStoreWithOut()
const locale = localeStore.getCurrentLocale
const handleAuthorized = () => {
  const { t } = useI18n()
  if (!isRelogin.show) {
    isRelogin.show = true
    ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {
      showCancelButton: false,
      closeOnClickModal: false,
      showClose: false,
      closeOnPressEscape: false,
      confirmButtonText: t('login.relogin'),
      type: 'warning'
    }).then(() => {
      resetRouter() // 重置静态路由表
      deleteUserCache() // 删除用户缓存
      removeToken()
      isRelogin.show = false
      // 干掉token后再走一次路由让它过router.beforeEach的校验
      window.location.href = window.location.href
    })
  }
  return Promise.reject(t('sys.api.timeoutMessage'))
}

interface RequestConfig extends AxiosRequestConfig {
  showErrorMessage?: boolean
  showSuccessMessage?: boolean
}

interface InternalRequestConfig extends InternalAxiosRequestConfig {
  showErrorMessage?: boolean
  showSuccessMessage?: boolean
}

interface requestResponse extends AxiosResponse {
  config: InternalRequestConfig
}

class Request {
  private instance: AxiosInstance

  constructor() {
    this.instance = axios.create({
      baseURL: base_url,
      timeout: request_timeout,
      headers: {
        'Content-Type': 'application/json',
        lang: locale.lang ?? 'zh-cn'
      }
    })
    // 全局请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalRequestConfig) => {
        // 携带token site-id
        if (getAccessToken()) {
          config.headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getAccessToken()
        }
        config.headers[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = getTenantId() || 1

        return config
      },
      (err: any) => {
        return Promise.reject(err)
      }
    )

    // 全局响应拦截器
    this.instance.interceptors.response.use(
      (response: requestResponse) => {
        if (response.request.responseType != 'blob') {
          const res = response.data
          if (res.code != 0) {
            this.handleAuthError(res.code)
            if (res.code != 401 && response.config.showErrorMessage !== false)
              this.showElMessage({
                message: res.msg,
                type: 'error',
                dangerouslyUseHTMLString: true,
                duration: 5000
              })
            return Promise.reject(new Error(res.msg || 'Error'))
          } else {
            if (response.config.showSuccessMessage) ElMessage({ message: res.msg, type: 'success' })
            return res
          }
        }
        return response.data
      },
      (err: any) => {
        this.handleNetworkError(err)
        return Promise.reject(err)
      }
    )
  }

  /**
   * 发送get请求
   * @param url
   * @param config
   * @returns
   */
  public get<T = any, R = AxiosResponse<T>>(url: string, config?: RequestConfig): Promise<R> {
    return this.instance.get(url, config)
  }

  /**
   * 发送get请求
   * @param url
   * @param config
   * @returns
   */
  public post<T = any, R = AxiosResponse<T>, D = any>(
    url: string,
    data?: D,
    config?: RequestConfig
  ): Promise<R> {
    return this.instance.post(url, data, config)
  }

  /**
   * 发送get请求
   * @param url
   * @param config
   * @returns
   */
  public put<T = any, R = AxiosResponse<T>, D = any>(
    url: string,
    data?: D,
    config?: RequestConfig
  ): Promise<R> {
    return this.instance.put(url, data, config)
  }

  /**
   * 发送get请求
   * @param url
   * @param config
   * @returns
   */
  public delete<T = any, R = AxiosResponse<T>>(url: string, config?: RequestConfig): Promise<R> {
    return this.instance.delete(url, config)
  }

  /**
   * 处理网络请求错误
   * @param err
   */
  private handleNetworkError(err: any) {
    let errMessage = ''

    if (err.response && err.response.status) {
      const errStatus = err.response.status
      switch (errStatus) {
        case 400:
          errMessage = t('axios.400')
          break
        case 401:
          errMessage = t('axios.401')
          break
        case 403:
          errMessage = t('axios.403')
          break
        case 404:
          const baseURL = isUrl(err.response.config.baseURL)
            ? err.response.config.baseURL
            : `${location.origin}${err.response.config.baseURL}`
          errMessage = baseURL + t('axios.baseUrlError')
          break
        case 405:
          errMessage = t('axios.405')
          break
        case 408:
          errMessage = t('axios.408')
          break
        case 409:
          errMessage = t('axios.409')
          break
        case 500:
          errMessage = t('axios.500')
          break
        case 501:
          errMessage = t('axios.501')
          break
        case 502:
          errMessage = t('axios.502')
          break
        case 503:
          errMessage = t('axios.503')
          break
        case 504:
          errMessage = t('axios.504')
          break
        case 505:
          errMessage = t('axios.505')
          break
      }
    }
    err.message.includes('timeout') && (errMessage = t('axios.timeout'))
    if (err.code == 'ERR_NETWORK') {
      const baseURL = isUrl(err.config.baseURL)
        ? err.config.baseURL
        : `${location.origin}${err.config.baseURL}`
      errMessage = baseURL + t('axios.baseUrlError')
    }
    err.config.showErrorMessage !== false &&
      errMessage &&
      this.showElMessage({
        dangerouslyUseHTMLString: true,
        duration: 5000,
        message: errMessage,
        type: 'error'
      })
  }

  private handleAuthError(code: number) {
    switch (code) {
      case 401:
        handleAuthorized()
        break
    }
  }

  private messageCache = new Map()

  private showElMessage(options: MessageParams) {
    const cacheKey = options.message
    const cachedMessage = this.messageCache.get(cacheKey)

    if (!cachedMessage || Date.now() - cachedMessage.timestamp > 5000) {
      // 5秒内重复内容不再弹出，可自定义过期时间
      this.messageCache.set(cacheKey, { timestamp: Date.now() })
      ElMessage(options)
    }
  }
}

export default new Request()
